import 'dart:math';

import 'package:flutter/material.dart';
import 'package:flutter_screenutil/flutter_screenutil.dart';
import 'package:tv_friso_screen/utils/share_pre_utils.dart';

import 'base_painter.dart';
import 'chart_bean.dart';

/// 双折线图 + 柱状图
class ChartColumnBarPainter extends BasePainter {
  double _fixedHeight = 0.0, _fixedWidth = 0.0; //宽高
  double value; //当前动画值
  List<ChartBean>? chartBeans;
  late double startX, endX, startY, endY;
  List<double> maxMin = [0, 0]; //存储极值
  List<double> maxMinRate = [0, 0]; //曲线图的最值
  Color rectColor; //柱状图默认的颜色
  bool isShowX; //是否显示x轴的文本
  late double rectWidth; //柱状图的宽度
  double fontSize; //刻度文本大小
  Color? fontColor; //文本颜色
  double rectRadius; //矩形的圆角
  //以下的四周圆角只有在 rectRadius 为0的时候才生效
  double rectRadiusTopLeft,
      rectRadiusTopRight,
      rectRadiusBottomLeft,
      rectRadiusBottomRight;
  bool _isAnimationEnd = false;
  bool isCanTouch;
  Color? rectShadowColor; //触摸时显示的阴影颜色
  bool isShowTouchShadow; //触摸时是否显示阴影
  bool isShowTouchValue; //触摸时是否显示值
  Offset? globalPosition; //触摸位置
  Map<Rect, double> rectMap = Map();
  String rightUnit = "";

  Path? path;
  Path? path2;
  final Map<double, Offset> _points = {};
  final Map<double, Offset> _points2 = {};

  bool isCurve = true; //是否为曲线

  double defaultRectPadding = 15; //默认柱状图的间隔
  double barPadding = 2; //两个柱状图中间的间距
  double basePadding = 8.w; //默认的边距
  static const Color defaultColor = Colors.deepPurple;
  static const Color defaultRectShadowColor = Colors.white;
  double paddingXY = 5; //距离两边XY轴的间距

  late Size mSizeUnit;

  ChartColumnBarPainter(
    this.chartBeans,
    this.rectColor, {
    this.value = 1,
    this.isShowX = false,
    this.fontSize = 12,
    this.fontColor,
    this.isCanTouch = false,
    this.isShowTouchShadow = true,
    this.isShowTouchValue = false,
    this.rectShadowColor,
    this.globalPosition,
    this.rectRadius = 0,
    this.rectRadiusTopLeft = 0,
    this.rectRadiusTopRight = 0,
    this.rectRadiusBottomLeft = 0,
    this.rectRadiusBottomRight = 0,
    this.rightUnit = "",
  });

  @override
  void paint(Canvas canvas, Size size) {
    _init(size);

    _drawX(canvas, size); //x轴刻度
    _drawYLine(canvas, size);
    _drawBar(canvas, size); //柱状图

    initPath(canvas, size);
    _drawLine(canvas, size); //曲线或折线
  }

  @override
  bool shouldRepaint(ChartColumnBarPainter oldDelegate) {
    _isAnimationEnd = oldDelegate.value == value;
    return oldDelegate.value != value || isCanTouch;
  }

  /// 初始化
  void _init(Size size) {
    startX = basePadding;
    endX = size.width - basePadding;
    startY = size.height - (isShowX ? basePadding * 3 : basePadding);
    endY = basePadding * 3;
    _fixedHeight = startY - endY;
    _fixedWidth = endX - startX;
    maxMin = calculateMaxMin2(chartBeans);
    maxMinRate = calculateDoubleRateMaxMin(chartBeans);

    //去除所有间隔之后的所有柱状图宽度(最多7个柱状图,6段)
    var maxRectWidth = _fixedWidth -
        (chartBeans!.length - 1) * defaultRectPadding -
        paddingXY * 2;
    rectWidth = maxRectWidth / chartBeans!.length; //单个柱状图的宽度
  }

  /// 计算Path
  void initPath(Canvas canvas, Size size) {
    if (path == null && path2 == null) {
      if ((chartBeans?.isNotEmpty ?? false) && maxMin[0] > 0) {
        path = Path();
        path2 = Path();

        double preX, preY, currentX, currentY;
        double preY2, currentY2;

        int length = chartBeans!.length > 7 ? 7 : chartBeans!.length;
        double W = (_fixedWidth - paddingXY * 2 - rectWidth) /
            (length - 1); //两个点之间的x方向距离

        for (int i = 0; i < length; i++) {
          if (i == 0) {
            startX =
                startX + defaultRectPadding * i + rectWidth * i + rectWidth / 2;
            var key = startX;
            var value =
                (startY - chartBeans![i].rate! / maxMinRate[0] * _fixedHeight);
            path!.moveTo(key, value);
            _points[key] = Offset(key, value);

            var value2 =
                (startY - chartBeans![i].rate2! / maxMinRate[0] * _fixedHeight);
            path2!.moveTo(key, value2);
            _points2[key] = Offset(key, value2);
            continue;
          }
          currentX = startX + W * i;
          preX = startX + W * (i - 1);

          preY = (startY -
              chartBeans![i - 1].rate! / maxMinRate[0] * _fixedHeight);
          currentY =
              (startY - chartBeans![i].rate! / maxMinRate[0] * _fixedHeight);
          _points[currentX] = Offset(currentX, currentY);

          preY2 = (startY -
              chartBeans![i - 1].rate2! / maxMinRate[0] * _fixedHeight);
          currentY2 =
              (startY - chartBeans![i].rate2! / maxMinRate[0] * _fixedHeight);
          _points2[currentX] = Offset(currentX, currentY2);

          if (isCurve) {
            path!.cubicTo(
              (preX + currentX) / 2,
              preY,
              (preX + currentX) / 2,
              currentY,
              currentX,
              currentY,
            );

            path2!.cubicTo(
              (preX + currentX) / 2,
              preY2,
              (preX + currentX) / 2,
              currentY2,
              currentX,
              currentY2,
            );
          } else {
            path!.lineTo(currentX, currentY);
            path2!.lineTo(currentX, currentY2);
          }
        }
      }
    }
  }

  /// xy轴刻度值
  void _drawX(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;

    var style = TextStyle(
      color: fontColor ?? defaultColor,
      fontSize: fontSize,
    );
    var mSize = calculateTextSize(maxMin[0].toString(), style);
    mSizeUnit = calculateTextSize(rightUnit, style);

    //重新计算startX 和 endX
    startX = mSize.width;
    // endX = size.width - startX;
    endX = size.width - mSizeUnit.width;
    _fixedWidth = endX - startX;

    //去除所有间隔之后的所有柱状图宽度(最多7个柱状图,6段)
    var maxRectWidth = _fixedWidth -
        (chartBeans!.length - 1) * defaultRectPadding -
        paddingXY * 2;
    rectWidth = maxRectWidth / chartBeans!.length; //单个柱状图的宽度

    //x轴的值
    for (int i = 0; i < chartBeans!.length; i++) {
      double x = startX + defaultRectPadding * i + rectWidth * i;

      TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
        text: TextSpan(
          text: chartBeans![i].x,
          style: TextStyle(
            color: fontColor ?? defaultColor,
            fontSize: fontSize,
          ),
        ),
      )
        ..layout(minWidth: rectWidth)
        ..paint(canvas, Offset(x, startY + basePadding));
    }

    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 0.5.w
      ..strokeCap = StrokeCap.round
      ..color = const Color(0xff0085F7)
      ..style = PaintingStyle.fill;

    //Y轴 刻度值  左边
    var paddingY = maxMin[0] / 6; //每一个等份的值
    for (var i = 0; i < 7; i++) {
      double y = startY - paddingY * i / maxMin[0] * _fixedHeight * value;
      TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
        text: TextSpan(
          text: (paddingY * i).ceil().toString(),
          style: TextStyle(
            color: fontColor ?? defaultColor,
            fontSize: fontSize,
          ),
        ),
      )
        ..layout(minWidth: rectWidth)
        ..paint(canvas, Offset(0, y - basePadding / 2));

      canvas.drawLine(Offset(startX, y), Offset(endX, y), paint); //X轴线
    }
  }

  /// 绘制Y轴 刻度线
  void _drawYLine(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;

    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 0.5.w
      ..strokeCap = StrokeCap.round
      ..color = const Color(0xff0085F7)
      ..style = PaintingStyle.fill;

    //左边Y轴的线
    canvas.drawLine(
        Offset(startX, paddingXY * 2), Offset(startX, startY), paint);

    //Y轴单位
    TextPainter(
      ellipsis: '.',
      maxLines: 1,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
      text: TextSpan(
        text: SharePreUtils.getLanguage() == "zh" ? "(单位:听)" : "Unit (tin)",
        style: TextStyle(
          color: fontColor ?? defaultColor,
          fontSize: fontSize,
        ),
      ),
    )
      ..layout(minWidth: rectWidth)
      ..paint(canvas, Offset(paddingXY, paddingXY - 1));

    //X轴单位
    TextPainter(
      ellipsis: '.',
      maxLines: 1,
      textAlign: TextAlign.center,
      textDirection: TextDirection.ltr,
      text: TextSpan(
        text: rightUnit,
        style: TextStyle(
          color: fontColor ?? defaultColor,
          fontSize: fontSize,
        ),
      ),
    )
      ..layout(minWidth: rectWidth)
      ..paint(canvas, Offset(endX, startY - 2));
  }

  /// 柱状图
  void _drawBar(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;
    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 5
      ..strokeCap = StrokeCap.round
      ..color = rectColor
      ..style = PaintingStyle.fill;

    if (maxMin[0] <= 0) return;
    //最多只绘制7组数据
    rectMap.clear();
    var length = min(7, chartBeans!.length);

    startX = startX + paddingXY;

    //柱状图
    for (int i = 0; i < length; i++) {
      if (chartBeans![i].color != null) {
        paint.color = chartBeans![i].color!;
      } else {
        paint.color = rectColor;
      }

      double left = startX + defaultRectPadding * i + rectWidth * i;
      double right = left + rectWidth;
      double currentHeight =
          startY - chartBeans![i].y / maxMin[0] * _fixedHeight * value;
      var rect = Rect.fromLTRB(left, currentHeight, right, startY);

      if (rectRadius != 0) {
        canvas.drawRRect(
          RRect.fromRectAndRadius(rect, Radius.circular(rectRadius)),
          paint,
        );
      } else {
        canvas.drawRRect(
          RRect.fromRectAndCorners(
            rect,
            topLeft: Radius.circular(rectRadiusTopLeft),
            topRight: Radius.circular(rectRadiusTopRight),
            bottomLeft: Radius.circular(rectRadiusBottomLeft),
            bottomRight: Radius.circular(rectRadiusBottomRight),
          ),
          paint,
        );
      }
      if (!rectMap.containsKey(rect)) rectMap[rect] = chartBeans![i].y;

      //第一个柱状图的值
      /* TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
        text: TextSpan(
          text: "${chartBeans![i].y}",
          style: TextStyle(color: fontColor, fontSize: fontSize),
        ),
      )
        ..layout(minWidth: rect!.width)
        ..paint(
          canvas,
          Offset(
            rect!.left,
            rect!.top - basePadding - 5,
          ),
        );

      //第二个柱状图的值
      TextPainter(
        ellipsis: '.',
        maxLines: 1,
        textAlign: TextAlign.center,
        textDirection: TextDirection.ltr,
        text: TextSpan(
          text: "${chartBeans![i].y2}",
          style: TextStyle(color: fontColor, fontSize: fontSize),
        ),
      )
        ..layout(minWidth: rect2!.width)
        ..paint(
          canvas,
          Offset(
            rect2!.left,
            rect2!.top - basePadding - 5,
          ),
        );*/
    }
  }

  /// 曲线或折线
  void _drawLine(Canvas canvas, Size size) {
    if (chartBeans?.isEmpty ?? true) return;
    var paint = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 2.w
      ..strokeCap = StrokeCap.round
      ..color = Colors.blue
      ..style = PaintingStyle.stroke;

    var paint2 = Paint()
      ..isAntiAlias = true
      ..strokeWidth = 2.w
      ..strokeCap = StrokeCap.round
      ..color = Colors.orange
      ..style = PaintingStyle.stroke;

    if (maxMin[0] <= 0) return;
    var pathMetrics = path!.computeMetrics(forceClosed: false);
    var list = pathMetrics.toList();
    var length = value * list.length.toInt();
    Path linePath = Path();
    Path shadowPath = Path();

    for (int i = 0; i < length; i++) {
      var extractPath = list[i].extractPath(
        0,
        list[i].length * value,
        startWithMoveTo: true,
      );
      linePath.addPath(extractPath, const Offset(0, 0));
      shadowPath = extractPath;
    }

    //第二条线
    Path linePath2 = Path();
    var pathMetrics2 = path2!.computeMetrics(forceClosed: false);
    var list2 = pathMetrics2.toList();
    var length2 = value * list2.length.toInt();

    for (int i = 0; i < length2; i++) {
      var extractPath = list2[i].extractPath(
        0,
        list2[i].length * value,
        startWithMoveTo: true,
      );
      linePath2.addPath(extractPath, const Offset(0, 0));
    }
    canvas.drawPath(linePath, paint);
    canvas.drawPath(linePath2, paint2);

    //画点
    if (_points.isNotEmpty) {
      var point = Paint()
        ..isAntiAlias = true
        ..strokeWidth = 2.w
        ..strokeCap = StrokeCap.round
        ..color = Colors.blue
        ..style = PaintingStyle.fill;

      _points.forEach((key, value) {
        canvas.drawCircle(value, 4.w, point);
      });
    }

    if (_points2.isNotEmpty) {
      var point = Paint()
        ..isAntiAlias = true
        ..strokeWidth = 2.w
        ..strokeCap = StrokeCap.round
        ..color = Colors.orange
        ..style = PaintingStyle.fill;

      _points2.forEach((key, value) {
        canvas.drawCircle(value, 4.w, point);
      });
    }
  }
}
